package com.echo.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.echo.AiManager.AiManager;
import com.echo.context.WisUserIdContext;
import com.echo.dto.ScheduleDTO;
import com.echo.entity.Exam;
import com.echo.entity.ExamAnalysis;
import com.echo.entity.Schedule;
import com.echo.entity.ScheduleDates;
import com.echo.mapper.ExamAnalysisMapper;
import com.echo.mapper.ExamMapper;
import com.echo.mapper.ScheduleDatesMapper;
import com.echo.mapper.ScheduleMapper;
import com.echo.service.IScheduleService;
import com.echo.vo.ExamToAiGenerateSchedule;
import com.echo.vo.ScheduleAiGenerateVo;
import com.echo.vo.ScheduleChangeVo;
import com.echo.vo.ScheduleVo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.echo.constant.AIRole.GENERATE_SCHEDULE_SYSTEM_MESSAGE;

/**
 * <p>
 * 存储计划总体信息的主表 服务实现类
 * </p>
 *
 * @author echo
 * @since 2024-11-13
 */
@Service
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper, Schedule> implements IScheduleService {
    @Autowired
    private ScheduleDatesMapper scheduleDatesMapper;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private ScheduleDatesServiceImpl scheduleDatesService;
    @Autowired
    private ScheduleServiceImpl scheduleService;
    @Autowired
    private ExamAnalysisMapper examAnalysisMapper;

    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private AiManager aiManager;

    private static final List<LocalTime> availableTimes = Arrays.asList(
            LocalTime.parse("09:00:00"),
            LocalTime.parse("10:00:00"),
            LocalTime.parse("14:00:00"),
            LocalTime.parse("16:00:00")
    );
    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void creatSchedule(ScheduleDTO scheduleDTO) {
        String userId = WisUserIdContext.getUserIdContext();
        Schedule schedule=new Schedule();
        List<String> dates=scheduleDTO.getDataList();
        String scheduleString = String.join(",", dates);
        BeanUtils.copyProperties(scheduleDTO,schedule);
        // 设置userId
        schedule.setUserId(userId);
        schedule.setCreateTime(new Date());
        schedule.setUpdateTime(new Date());
        schedule.setDates(scheduleString);
        schedule.setRemindTime(scheduleDTO.getRemindTime());
        String scheduleId=IdUtil.simpleUUID();
        schedule.setScheduleId(scheduleId);
        //这里差设置时间和list<string>datalist
        scheduleMapper.insert(schedule);
        // Step 2: 将多个日期存入 schedule_dates 表中
        List<ScheduleDates> scheduleDatesList = new ArrayList<>();
        System.out.println("dates"+dates);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (String dateStr : dates) {
            ScheduleDates scheduleDates = new ScheduleDates();
            scheduleDates.setId(IdUtil.simpleUUID());
            scheduleDates.setUserId(userId);
            scheduleDates.setScheduleId(scheduleId);  // 关联的计划 ID
            // 转化格式
            scheduleDates.setDate(LocalDate.parse(dateStr, formatter));// 将字符串日期转换为 LocalDate
            System.out.println(LocalDate.parse(dateStr, formatter));
            scheduleDatesList.add(scheduleDates);
        }
        // Step 3: 使用 MyBatis-Plus 的 saveBatch 方法批量插入
        scheduleDatesService.saveBatch(scheduleDatesList);

    }

    @Override
    public  List<ScheduleVo> getDaySchedule(LocalDate localDate) {
        String userId = WisUserIdContext.getUserIdContext();
        QueryWrapper<ScheduleDates> wrapper=new QueryWrapper<>();
        //这里就得到了对应天的schedule的id，然后再去查询对应的日程
        wrapper.lambda()
                .eq(ScheduleDates::getUserId,userId)
                .eq(ScheduleDates::getDate,localDate);
        List<ScheduleDates> scheduleDates = scheduleDatesMapper.selectList(wrapper);
        //得到对应的id集合
        List<String> scheduleIds = scheduleDates.stream()
                .map(ScheduleDates::getScheduleId)
                .distinct()
                .collect(Collectors.toList());

        //这里去封装对应的计划并返回
        List<Schedule> schedules = scheduleMapper.selectBatchIds(scheduleIds);
        List<ScheduleVo> scheduleVos=new ArrayList<>();
        for (Schedule schedule : schedules) {
            ScheduleVo scheduleVo=new ScheduleVo();
            BeanUtils.copyProperties(schedule,scheduleVo);
            String dates = schedule.getDates();
            // 使用 split() 方法将字符串按逗号分割，结果是一个数组
            String[] dateArray = dates.split(",");
            // 这里返回的是每个日程的list 日期集合
            List<String> dateList = Arrays.asList(dateArray);
            scheduleVo.setDateList(dateList);
            scheduleVos.add(scheduleVo);
        }
        return scheduleVos;
    }
    //这里首先去得到历史的评价【10条】
    @Override
    public List<ScheduleDTO> generateAiSchedule(String type) throws JsonProcessingException {
        String userId = WisUserIdContext.getUserIdContext();
        QueryWrapper<ExamAnalysis> wrapperSummary=new QueryWrapper<>();
        wrapperSummary.lambda()
                .eq(ExamAnalysis::getUserId,userId)
                .eq(ExamAnalysis::getExamType,type)
                .orderByDesc(ExamAnalysis::getCreateTime)
                .last("LIMIT 10");
        List<ExamAnalysis> examAnalyses = examAnalysisMapper.selectList(wrapperSummary);
        //得到历史评价
        List<String> summaryList=new ArrayList<>();
        for (ExamAnalysis examAnalysis : examAnalyses) {
            summaryList.add(examAnalysis.getPerformanceSummary());
        }
        String summaryJson = objectMapper.writeValueAsString(summaryList);

        //得到最近做的题目的id
        List<String> examIdList=new ArrayList<>();
        for (ExamAnalysis examAnalysis : examAnalyses) {
            //todo:getPerformanceSummary这个的格式
            summaryList.add(examAnalysis.getPerformanceSummary());
            examIdList.add(examAnalysis.getExamId());
        }
        //这里去得到对应的id的试卷信息，方便ai去识别
        List<Exam> exams = examMapper.selectBatchIds(examIdList);
        List<ExamToAiGenerateSchedule> examToAiGenerateScheduleList=new ArrayList<>();
        for (Exam exam : exams) {
            ExamToAiGenerateSchedule examToAiGenerateSchedule=new ExamToAiGenerateSchedule();
            BeanUtils.copyProperties(exams,examToAiGenerateSchedule);
            examToAiGenerateScheduleList.add(examToAiGenerateSchedule);
        }

        // 上面是得到10张做过的试卷去选择
        // 下面是在所有科目试卷中挑选10张没做过的去选择，分别要每个科目都有3张，让ai去选择
        QueryWrapper<Exam> wrapperAll=new QueryWrapper<>();
        wrapperAll.lambda()
                .eq(Exam::getExamType,type)
                .orderByDesc(Exam::getCreateTime)
                .last("LIMIT 10");
        List<Exam> allExams = examMapper.selectList(wrapperAll);
        //下面是去分类的
        /*// 存储最终的10张试卷
        List<Exam> endExam = new ArrayList<>();
        // 按科目对试卷分组
        Map<String, List<Exam>> examsBySubject = allExams.stream()
                .collect(Collectors.groupingBy(Exam::getExamType));

        // 确保每个科目至少有3张试卷，并加入 endExam
        for (List<Exam> exams2 : examsBySubject.values()) {
            // 从每个科目中获取最多3张试卷，避免科目数量不足的问题
            endExam.addAll(exams2.stream().limit(2).collect(Collectors.toList()));
        }

        // 如果当前试卷数量超过10张，只保留前10张
        if (endExam.size() > 5) {
            endExam = endExam.subList(0, 5);
        }

        // 如果当前试卷数量少于10张，从剩余的试卷中补足
        if (endExam.size() < 5) {
            List<Exam> finalEndExam = endExam;
            List<Exam> remainingExams = allExams.stream()
                    .filter(exam -> !finalEndExam.contains(exam)) // 排除已经选择的试卷
                    .collect(Collectors.toList());

            int remainingNeeded = 5 - endExam.size();
            endExam.addAll(remainingExams.stream().limit(remainingNeeded).collect(Collectors.toList()));
        }
        */
        // 这里就会存储着不同科目的试卷
        for (Exam exam : allExams) {
            ExamToAiGenerateSchedule examToAiGenerateSchedule=new ExamToAiGenerateSchedule();
            BeanUtils.copyProperties(exam,examToAiGenerateSchedule);
            examToAiGenerateScheduleList.add(examToAiGenerateSchedule);
        }

        String newExamJson = objectMapper.writeValueAsString(examToAiGenerateScheduleList);

        //现在ai有了历史评价，做过的试卷，新的试卷，然后让ai去生成什么呢？
        //生成 1.让根据历史评价分析学生的情况[不用返回]
        //     2.让ai从我的试卷【做过的试卷和新的试卷中选择出6套适合的试卷】
        //     3.让ai根据日程计划的字段，将对应的试卷的名称、描述、type填写进日程的内容description中，并自动生成计划的时间
        //      复习日期的格式： 2024-12-11,2024-12-12
        //      提醒时间：      HH-MM-SS

        // 构建当前日期
        String currentDate = LocalDate.now().toString();

        // 构建 AI 请求数据，包含历史评价记录、新试卷列表和当前日期
        String userMessage = String.format("{\"historySummary\": %s, \"newExamList\": %s, \"currentDate\": \"%s\"}", summaryJson, newExamJson, currentDate);
        System.out.println(userMessage);
        // 调用AI
        String scheduleResponse2 = aiManager.doSyncStableRequest(GENERATE_SCHEDULE_SYSTEM_MESSAGE, userMessage);

        String scheduleResponse = extractJsonContent(scheduleResponse2);
        System.out.println("sc"+scheduleResponse);
        // 将AI返回的数据解析并存入 ScheduleAiGenerateVo
        List<ScheduleAiGenerateVo> scheduleList = objectMapper.readValue(scheduleResponse, objectMapper.getTypeFactory().constructCollectionType(List.class, ScheduleAiGenerateVo.class));
        List<ScheduleDTO> scheduleDTOList=new ArrayList<>();

        // 获取当天日期，格式为 "yyyy-MM-dd"
        String today = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        for (ScheduleAiGenerateVo scheduleAiGenerateVo : scheduleList) {
            ScheduleDTO scheduleDTO = new ScheduleDTO();
            BeanUtils.copyProperties(scheduleAiGenerateVo, scheduleDTO);

            // 随机选择一个时间
            Random random = new Random();
            LocalTime randomTime = availableTimes.get(random.nextInt(availableTimes.size()));
            scheduleDTO.setRemindTime(randomTime);

            // 修改 dataList 的第一个日期为当天
            List<String> dateList = scheduleAiGenerateVo.getDateList();
            if (dateList != null && !dateList.isEmpty()) {
                dateList.set(0, today); // 替换第一个日期为当天
            }
            scheduleDTO.setDataList(dateList);

            // 设置为 AI 生成的任务
            scheduleDTO.setIsAiGenerated(true);

            System.out.println("Modified ScheduleDTO: " + scheduleDTO);
            scheduleDTOList.add(scheduleDTO);

            // 如果需要保存，可以在这里调用保存方法
            // creatSchedule(scheduleDTO);
        }
        return scheduleDTOList;
    }

    @Override
    public void changeSchedule(String scheduleId) {
        QueryWrapper<Schedule> wrapperQ=new QueryWrapper<>();
        wrapperQ.lambda()
                .eq(Schedule::getScheduleId,scheduleId);
        Schedule schedule = scheduleMapper.selectOne(wrapperQ);
        int status=schedule.getStatus();
        //取之相反的状态
        if(status==1){
            status=0;
        }else {
            status=1;
        }
        //
        UpdateWrapper<Schedule> wrapper=new UpdateWrapper<>();
        wrapper.lambda()
                .eq(Schedule::getScheduleId,scheduleId)
                .set(Schedule::getStatus,status);
        scheduleMapper.update(null,wrapper);

    }



  /*  @Override
    public void changeScheduleAll(ScheduleChangeVo scheduleChangeVo) {
        String scheduleId = scheduleChangeVo.getScheduleId();

        UpdateWrapper<Schedule> wrapper=new UpdateWrapper<>();
        wrapper.lambda()
                .eq(Schedule::getScheduleId,scheduleId);
        Schedule schedule=new Schedule();
        BeanUtils.copyProperties(scheduleChangeVo,schedule);
        scheduleMapper.update(schedule,wrapper);
    }*/

    @Override
    public void changeDaySchedule(ScheduleChangeVo scheduleChangeVo) {
        String userId = WisUserIdContext.getUserIdContext();
        List<String> dataList = scheduleChangeVo.getDateList();
        String scheduleString = String.join(",", dataList);
        String scheduleId = scheduleChangeVo.getScheduleId();
        Schedule schedule=new Schedule();
        BeanUtils.copyProperties(scheduleChangeVo,schedule);
        schedule.setDates(scheduleString);
        schedule.setUserId(userId);
        UpdateWrapper<Schedule> wrapper=new UpdateWrapper<>();
        wrapper.lambda()
                .eq(Schedule::getScheduleId,scheduleChangeVo.getScheduleId());
        scheduleMapper.update(schedule,wrapper);
        //1.这里应该先去删除该scheduleId的date，下面再去存，避免重复
        QueryWrapper<ScheduleDates>scheduleDatesQueryWrapper=new QueryWrapper<>();
        scheduleDatesQueryWrapper.lambda()
                .eq(ScheduleDates::getScheduleId,scheduleId);
        scheduleDatesMapper.delete(scheduleDatesQueryWrapper);
        // Step 2: 将多个日期存入 schedule_dates 表中
        List<ScheduleDates> scheduleDatesList = new ArrayList<>();
        System.out.println("dates"+dataList);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (String dateStr : dataList) {
            ScheduleDates scheduleDates = new ScheduleDates();
            scheduleDates.setId(IdUtil.simpleUUID());
            scheduleDates.setUserId(userId);
            scheduleDates.setScheduleId(scheduleId);  // 关联的计划 ID
            // 转化格式
            scheduleDates.setDate(LocalDate.parse(dateStr, formatter));// 将字符串日期转换为 LocalDate
            System.out.println(LocalDate.parse(dateStr, formatter));
            scheduleDatesList.add(scheduleDates);
        }
        // Step 3: 使用 MyBatis-Plus 的 saveBatch 方法批量插入
        scheduleDatesService.saveBatch(scheduleDatesList);
    }

    public static String extractJsonContent(String response) {
        int startIndex = response.indexOf("[");
        int endIndex = response.lastIndexOf("]") + 1;

        if (startIndex != -1 && endIndex != -1 && startIndex < endIndex) {
            return response.substring(startIndex, endIndex);
        } else {
            throw new IllegalArgumentException("无法找到有效的 JSON 部分");
        }
    }
}
